/*************************************************
 * File Name: AppContext.java
 * Package Name: com.sensorfriendly
 * 
 * Purpose:
 * This file contains the main application
 * context and is responsible for the following 
 * tasks:
 * - Initializing and performing the DB
 * - Setting up the directories
 * - Maintaining pagination
 * - All data updates in UI are made through here.
 *************************************************/

package com.sensorfriendly;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Environment;
import android.preference.PreferenceManager;
import android.widget.Toast;

import com.google.gson.Gson;
import com.sensorfriendly.model.Message;
import com.sensorfriendly.model.Scenario;
import com.sensorfriendly.provider.impl.MessageDBImpl;
import com.sensorfriendly.provider.impl.ScenarioDBImpl;

public class AppContext extends Application {

	private int currentPage;
	private int[] buttonIds;
	private int[] buttonBGIds;
	private int maxPageNum;
	private int pageResidual;
	private int[] themeIds;
	private boolean micSupport;
	
	private ScenarioDBImpl scenarioDB;
	private MessageDBImpl messageDB;

	@Override
	public void onCreate() {
		super.onCreate();
		currentPage = 0;
		/******************************************
		 * Make the directories needed for each
		 * scenario
		 ******************************************/
		String extStorage = Environment.getExternalStorageDirectory().getAbsolutePath();
		File appExtDir = new File(extStorage+"/"+AppConstants.APP_EXT_FOLDER);
		if(!appExtDir.exists()){
			appExtDir.mkdir();
		}
		File audioDir = new File(appExtDir.getAbsoluteFile()+"/"+AppConstants.MESSAGE_AUDIO_FOLDER);
		if(!audioDir.exists()){
			audioDir.mkdir();
		}

		/*******************************************
		 * Check for mic support in the device
		 *******************************************/
		micSupport = getPackageManager().hasSystemFeature("android.hardware.microphone");			
		SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
		boolean initDB = sharedPrefs.getBoolean(
				AppConstants.PREFERENCE_INIT_DB, true);

		/*******************************************
		 * Initialize the Database connection
		 *******************************************/
		if (initDB) {
			initializeDB();
		} 
		scenarioDB = new ScenarioDBImpl(this);
		messageDB = new MessageDBImpl(this);
		
		initializeContext();
	}

	/*******************************************
	 * Initialize the context of the file
	 *******************************************/
	private void initializeContext() {
		calculatePageNum();
		buttonIds = new int[4];
		buttonIds[0] = R.id.event1;
		buttonIds[1] = R.id.event2;
		buttonIds[2] = R.id.event3;
		buttonIds[3] = R.id.event4;

		buttonBGIds = new int[4];
		buttonBGIds[0] = R.id.event1_bg;
		buttonBGIds[1] = R.id.event2_bg;
		buttonBGIds[2] = R.id.event3_bg;
		buttonBGIds[3] = R.id.event4_bg;
		
		
		themeIds = new int[6];
		themeIds[0] = R.array.theme1;
		themeIds[1] = R.array.theme2;
		themeIds[2] = R.array.theme3;
		themeIds[3] = R.array.theme4;
		themeIds[4] = R.array.theme5;
		themeIds[5] = R.array.theme6;
	}
	
	/*******************************************
	 * Calculate the max number of pages
	 * by dividing the number of scenarios by
	 * ITEM_PER_PAGE + 1
	 *******************************************/
	private void calculatePageNum() {
		int scenariosCount = scenarioDB.getScenarioCount();
		maxPageNum = scenariosCount/AppConstants.ITEM_PER_PAGE;
		if((pageResidual=scenariosCount%AppConstants.ITEM_PER_PAGE) > 0){
			maxPageNum +=1;
		}
	}
	
	/*******************************************
	 * Calculate the next page number so that we can
	 * go back to the first page from the last
	 * page
	 *******************************************/
	public int nextPage() {
		currentPage = (currentPage + 1) % maxPageNum;
		return currentPage;
	}

	/*******************************************
	 * Calculate the previous page number so that we can
	 * go back to the last page from the first
	 * page
	 *******************************************/
	public int previousPage() {
		if (currentPage == 0) {
			currentPage = maxPageNum - 1;
		} else {
			currentPage = (currentPage - 1) % maxPageNum;
		}
		return currentPage;
	}

	/*******************************************
	 * Gets the list of MESSAGES under the 
	 * given SCENARIO name
	 *******************************************/
	public List<Message> getScenarioMessages(String scenarioName) {
		Scenario sceanrio = scenarioDB.getScenario(scenarioName);
		if(sceanrio == null){
			return null;
		}
		return sceanrio.getMessages();
	}

	/*******************************************
	 * Adds a new Scenario to the DB if it is not a 
	 * duplicates and recalculates the
	 * maxPageNum
	 *******************************************/
	public boolean addScenario(Scenario s) {
		boolean duplicate = scenarioDB.insertScenario(s);
		if(duplicate){
			return duplicate;
		}
		if((pageResidual+=1)%AppConstants.ITEM_PER_PAGE ==1){
			maxPageNum++;
		}
		return false;
	}

	/*******************************************
	 * Adds a new Message to the DB 
	 *******************************************/
	public void addNewMessage(Message message) {
		messageDB.insertMessage(message);
	}

	/*******************************************
	 * Deletes a Scenario from the DB 
	 * recalculates the maxPageNum
	 *******************************************/
	public void deleteScenario(String scenarioName) {
		scenarioDB.deleteScenario(scenarioName);
		if(pageResidual == 1){
			pageResidual = AppConstants.ITEM_PER_PAGE;
			maxPageNum--;
		}else{
			pageResidual--;
		}
	}

	/*******************************************
	 * Deletes the given messages from the DB
	 *******************************************/
	public void deleteMessages(Message message) {
		messageDB.deleteMessage(message);
	}

	/*******************************************
	 * Updates the given Scenario names in the DB
	 *******************************************/
	public void editScenario(String oldName, Scenario scenario) {
		scenarioDB.updateScenario(oldName, scenario);
	}
	
	/*******************************************
	 * Updates the given Message in the DB
	 *******************************************/
	public void editMessage(String oldContent, Message message) {
		messageDB.updateMessage(oldContent, message);
	}
	
	/*******************************************
	 * Gets a list of Scenarios for the given
	 * page number
	 *******************************************/
	public List<Scenario> getCurrentPageScenearios(int pageNum) {
		List<Scenario> scenarios = scenarioDB.getScenariosForPage(pageNum);
		return scenarios;
	}

	/*******************************************
	 * Gets the Mic support boolean
	 *******************************************/
	public boolean isMicSupport() {
		return micSupport;
	}

	/*******************************************
	 * Gets the Theme ID
	 *******************************************/
	public int[] getThemeIds() {
		return themeIds;
	}

	/*******************************************
	 * Gets the List of all the scenarios
	 *******************************************/
	public List<Scenario> getAllScenarios() {
		return scenarioDB.getAllScenarios();
	}

	/*******************************************
	 * Gets the current page number
	 *******************************************/
	public int getCurrentPage() {
		if(!(currentPage < maxPageNum)){
			currentPage = maxPageNum -1;
		}	
		return currentPage;
	}

	/*******************************************
	 * Sets the current page number
	 *******************************************/
	public void setCurrentPage(int currentPage) {
		this.currentPage = currentPage;
	}

	/*******************************************
	 * Gets the Button IDs for the 4 buttons 
	 * of the main navigation screen
	 *******************************************/
	public int[] getButtonIds() {
		return buttonIds;
	}

	/*******************************************
	 * Gets the Background ID for the buttons
	 *******************************************/
	public int[] getButtonBGIds() {
		return buttonBGIds;
	}
	
	/*******************************************
	 * Initialize the DB with the baseline info
	 *******************************************/
	private void initializeDB() {
		String[] care = new String[] { "Did you shower?",
				"Hair Combed? Deodorant?", "Hands and face clean?",
				"Clothes weather ready?" };
		String[] family = new String[] { "Pickup what you drop",
				"Share bathroom", "Be polite at the dinner table" };
		String[] friends = new String[] {
				"No pushing and pulling. Use words only.",
				"Wait for your turn", "Greet People" };
		String[] school = new String[] { "See a bully, tell the teacher",
				"Stay with class, no roaming",
				"Wash hands before leaving the bathroom.",
				"What do do next? Ask teacher." };
		String[] restraunt = new String[] {
				"Be preprared with a second choice", "Wait for your turn",
				"Say thank you", "List your favorite food" };
		String[] shopping = new String[] { "List shirt, shoe, pants size",
				"Ask how clothes look on you",
				"Ask if the item you choose is worth the money",
				"try on before you buy" };
		String[] travel = new String[] { "Wear seat belt" };
		String[] bedtime = new String[] { "Finished homework?" };

		Map<String, List<String>> categoryMessages = new HashMap<String, List<String>>();

		// Populate the messages under each category
		categoryMessages.put("care", Arrays.asList(care));
		categoryMessages.put("family", Arrays.asList(family));
		categoryMessages.put("friends", Arrays.asList(friends));
		categoryMessages.put("restaurant", Arrays.asList(restraunt));
		categoryMessages.put("shopping", Arrays.asList(shopping));
		categoryMessages.put("travel", Arrays.asList(travel));
		categoryMessages.put("bedtime", Arrays.asList(bedtime));
		categoryMessages.put("school", Arrays.asList(school));

		List<Scenario>scenarios = new ArrayList<Scenario>();
		for (String sName : categoryMessages.keySet()) {
			Scenario s = new Scenario(sName);
			for (String msg : categoryMessages.get(sName)) {
				Message newMessage = new Message();
				newMessage.setMessageContent(msg);
				newMessage.setScenarioName(s.getName());
				s.addMessage(newMessage);
			}
			scenarios.add(s);
		}
		
		// Insert the Scenarios and their messages into the DB
		ScenarioDBImpl scenarioDB = new ScenarioDBImpl(this);
		for(Scenario s : scenarios){
			scenarioDB.insertScenario(s);
		}
		
		// Commit to the DB
		SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
		Editor editor = sharedPrefs.edit();
		editor.putBoolean(AppConstants.PREFERENCE_INIT_DB, false);
		editor.commit();
	}
}
